const { chromium, firefox, webkit} = require('playwright');
const config = require("./config/scrapy.config.json");
const fs = require("fs");
const path = require('path');
const moment = require("moment");
const readline = require("node:readline");
  
var Cookie = ""

const getTextFromConsole = ()=>{
    return new Promise((resolve,reject)=>{
        const rl = readline.createInterface({
            input:process.stdin,
            output:process.stdout
        })
        rl.question(`Please input the validation code.\n`,code=>{
            console.log(`input value is : ${code}`)
            resolve(code)
            rl.close();
        });
    })
}

//url example: https://www.amazon.com/s?k=green+T-Shirt&ref=nb_sb_noss
const startPlaywright = (zipcode,keyword,proxies)=>{

    return new Promise((resolve,reject)=>{
     
    (async () => {

    const b = [webkit,chromium,firefox,][config.browserIdx];  
    var options = {
        headless: !config.showBrowser,
        proxy:{server:`http://172.64.40.184`},
        args:["--window-position=0,0"]
    }
    if(proxies && proxies.length > 0){
        const randomIdx = Math.floor(Math.random()*proxies.length);
        let proxy = proxies[randomIdx]
        if(proxy.ip){
            options.proxy = {server:`http://${proxy.ip}:${proxy.port}`}
        }else{
            throw new Error("no ip found in specified proxy")
        }
    }
    const browser = await b.launch(options);    
    console.log(`will use proxy:${options.proxy.server}`)
    try{
        var requestHeaders = {
            Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            'Accept-Language': 'en',
            'Sec-Ch-Ua':'"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"',
            'Sec-Ch-Ua-Mobile':'?0',
            'Sec-Ch-Ua-Platform':"macOS",
            'Sec-Ch-Viewport-Width':2578.3,
            'Sec-Fetch-Dest':'document',
            'Sec-Fetch-Mode':'navigate',
            'Sec-Fetch-Site':'same-origin',
            'Sec-Fetch-User':'?1',
            'Upgrade-Insecure-Requests':1,
            'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
        }
        const context = await browser.newContext(requestHeaders);
        if(Cookie && Cookie.length > 0){
            // await context.addCookies(Cookie)
        }
        context.setDefaultTimeout(config.waitTimeout);
        //打开亚马逊页面
        const page = await context.newPage({});
        await page.setViewportSize({width:500,height:800})
        const url = `https://www.google.com`
        console.log(`load page : ${url}`)
        await page.goto(url,{timeout:config.loadTimeout});
        //看见验证码
        if(await page.getByPlaceholder('Type characters').isVisible()){
            await page.getByPlaceholder('Type characters').click();
            const imgurl = await page.locator('form').getByRole('img').getAttribute('src');
            console.log("got validate code img url: "+imgurl);
            
            const code = await getTextFromConsole();
            console.log(`input validation code is : ${code}`);

            await page.getByPlaceholder('Type characters').fill(code);
            await page.getByRole('button', { name: 'Continue shopping' }).click();
            //添加超时，避免提前判断
            await page.waitForTimeout(5000);
            console.log("要手动处理验证码问题。。。 npx playwright 。。。。")
        }
       
        //看见看门狗图片
        const watchdogSelector = `img[alt="Sorry! Something went wrong on our end. Please go back and try again or go to Amazon's home page."]`;
        const dog = await page.locator(watchdogSelector);
        if(await dog.isVisible()){
            //看到看门狗，用命令重启浏览器，或者打开到亚马逊主页
            console.log("meet the watch dog..., or please run npx playwright")
            await page.goto("https://www.amazon.com")
            throw new Error("Meet the watch dog");
        }
        ///输邮编
        if(await page.locator("div.a-declarative.nav-global-location-slot-upsell-false").isVisible()){
            //需要登录
            await page.locator("div.a-declarative.nav-global-location-slot-upsell-false").click();
            //TODO: 如果看到要等录的页面的处理
        }else if(await page.locator("#glow-ingress-block").isVisible()){
            console.log("here we go 1")
            await page.locator("#glow-ingress-block").click()
            await page.getByLabel('or enter a US zip code').click();
            await page.getByLabel('or enter a US zip code').fill(zipcode);    
        }
        else if(await page.locator('#nav-global-location-popover-link').isVisible()){
            //不需要登录
            console.log("here we go 2")
            await page.locator('#nav-global-location-popover-link').click();
            await page.getByLabel('or enter a US zip code').click();
            await page.getByLabel('or enter a US zip code').fill(zipcode);    
        }else{
            const html = await page.content();
            fs.writeFileSync(path.resolve(".",'zipcodeerror.html'),html)
            reject(new Error("Can not see delivery to button"))
            return;
        }
        //应用邮编
        try{
            await page.getByLabel('Apply').click();
            await page.getByRole('button', { name: 'Continue' }).click();
        }catch(e){
            const content = await page.content();
            const dt = moment().format("yyyy-MM-dd_HH-mm-ss")
            // fs.writeFileSync(path.resolve(".",dt,keyword+'.exception.html'),e.toString())
            try{
                await page.getByRole('button', { name: 'Done' }).click();
            }catch(e){
                console.log("No Continue Button either Done button")
                reject(e)
                return;
            }
        }
        const deliveryto = await page.locator("span#glow-ingress-line2",{hasText:zipcode})
        const deliveryText = await deliveryto.innerText()

        if(deliveryText.includes(zipcode)){
            
            //输关键字
            await page.getByPlaceholder('Search Amazon').fill(keyword);
            //点按回车键
            await page.getByPlaceholder('Search Amazon').press('Enter');      
            
            await page.waitForLoadState("load");

            Cookie = await page.context().cookies(["https://amazon.com"]);

            const html = await page.content();
            
            console.log(`got html of url ${page.url()}`)
            const divLocator = await page.locator("div[data-asin]");
            const divs = await divLocator.all();
            var values = [];
            for(var i=0;i<divs.length;i++){
                let divEle = divs[i];
        
                let dataAsin = await divEle.getAttribute("data-asin");
        
                if(!dataAsin || dataAsin.length === 0){
                    continue;
                }
                let selector = "div[data-asin='" + dataAsin + "'] span";
                let span = await page.locator(selector);
                let title = ""
                try{
                    title = await span.first().innerText({timeout:config.waitTimeout});
                }catch(e){
                    console.error(e)
                    title = ""
                }

                const sellamountSelector = "div[data-asin='" + dataAsin + "'] span.a-size-base";

                var amount = ""
                try{
                    if(await page.locator(sellamountSelector,{hasText:"bought in past month"}).isVisible()){
                        const amountSpan = await page.locator(sellamountSelector,{hasText:"bought in past month"});
                        amount = await amountSpan.innerText();
                    }    
                }catch(e){
                    //
                    console.log("can not find bought count, but it is not an issue");
                }
                values.push({
                    dataAsin:dataAsin||"",
                    title:title||"",
                    amount
                });   
            }
    
            const dataitems = values||[]
            const result = {html,dataitems}
            console.log(`got result: ${JSON.stringify(result)}`.yellow)
            await page.close()
            await context.close();
            await browser.close();
            resolve(result);
        }else{
            console.log(`---------- Delivery Code is ${deliveryto} on : zipcode: ${zipcode}, keyword: ${keyword}`)
            reject(new Error("DeliveryError"));
        }
    }catch(e){
        reject(e)
    }
    })();})

}

module.exports = {
    startPlaywright
}